package com.cloud.security.aop;

import com.cloud.common.domain.Result;
import com.cloud.domain.LoginUser;
import com.cloud.domain.UserProject;
import com.cloud.exception.LoginException;
import com.cloud.utils.SecurityUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * Security 自定义权限校验
 *
 * @author yzj
 */
@Aspect
@Component
public class SecurityAuthorizeAspect {

    public SecurityAuthorizeAspect() {
    }

    /**
     * 设置操作切入点
     */
    @Pointcut("@annotation(com.cloud.security.aop.RequestPermissions)")
    public void authPointCut() {
    }

    /**
     * @param joinPoint 切面对象
     * @return 底层方法执行后的返回值
     * @throws Throwable 底层方法抛出的异常
     */
    @Around("authPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequestPermissions permission = method.getAnnotation(RequestPermissions.class);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (ObjectUtils.isEmpty(loginUser)) {
            return Result.message(LoginException.USER_NO_AUTHORITY.getCode(),
                    "检验失败:获取账户登录信息失败");
        }
        UserProject userProject = loginUser.getUserProject();
        if (ObjectUtils.isEmpty(userProject)) {
            return Result.message(LoginException.USER_NO_AUTHORITY.getCode(),
                    "检验失败:获取登录系统信息失败");
        }
        Set<String> permissions = userProject.getPermissions();
        if (ObjectUtils.isEmpty(permissions)) {
            return Result.message(LoginException.USER_NO_AUTHORITY.getCode(),
                    "检验失败:该应用未配置访问权限");
        }
        if (!permissions.contains(permission.value())) {
            return Result.message(LoginException.USER_NO_AUTHORITY.getCode(),
                    LoginException.USER_NO_AUTHORITY.getMsg());
        }
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            // 底层方法抛出的异常
            throw e;
        }
    }

}
